home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / Development / ncurses-5.3 / tack / menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-27  |  8.4 KB  |  422 lines

  1. /*
  2. ** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
  3. ** 
  4. ** This file is part of TACK.
  5. ** 
  6. ** TACK is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2, or (at your option)
  9. ** any later version.
  10. ** 
  11. ** TACK is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. ** 
  16. ** You should have received a copy of the GNU General Public License
  17. ** along with TACK; see the file COPYING.  If not, write to
  18. ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. ** Boston, MA 02111-1307, USA.
  20. */
  21.  
  22. #include <tack.h>
  23.  
  24. MODULE_ID("$Id: menu.c,v 1.2 2000/03/04 21:13:53 tom Exp $")
  25.  
  26. /*
  27.    Menu control
  28.  */
  29.  
  30. static void test_byname(struct test_menu *, int *, int *);
  31.  
  32. struct test_list *augment_test;
  33. char prompt_string[80];    /* menu prompt storage */
  34.  
  35. /*
  36. **    menu_prompt()
  37. **
  38. **    Print the menu prompt string.
  39. */
  40. void
  41. menu_prompt(void)
  42. {
  43.     ptext(&prompt_string[1]);
  44. }
  45.  
  46. /*
  47. **    menu_test_loop(test-structure, state, control-character)
  48. **
  49. **    This function implements the repeat test function.
  50. */
  51. static void
  52. menu_test_loop(
  53.     struct test_list *test,
  54.     int *state,
  55.     int *ch)
  56. {
  57.     int nch, p;
  58.  
  59.     if ((test->flags & MENU_REP_MASK) && (augment_test != test)) {
  60.         /* set the augment variable (first time only) */
  61.         p = (test->flags >> 8) & 15;
  62.         if ((test->flags & MENU_REP_MASK) == MENU_LM1) {
  63.             augment = lines - 1;
  64.         } else
  65.         if ((test->flags & MENU_ONE_MASK) == MENU_ONE) {
  66.             augment = 1;
  67.         } else
  68.         if ((test->flags & MENU_LC_MASK) == MENU_lines) {
  69.             augment = lines * p / 10;
  70.         } else
  71.         if ((test->flags & MENU_LC_MASK) == MENU_columns) {
  72.             augment = columns * p / 10;
  73.         } else {
  74.             augment = 1;
  75.         }
  76.         augment_test = test;
  77.         set_augment_txt();
  78.     }
  79.     do {
  80.         if ((test->flags | *state) & MENU_CLEAR) {
  81.             put_clear();
  82.         } else
  83.         if (line_count + test->lines_needed >= lines) {
  84.             put_clear();
  85.         }
  86.         nch = 0;
  87.         if (test->test_procedure) {
  88.             /* The procedure takes precedence so I can pass
  89.                the menu entry as an argument.
  90.             */
  91.             can_test(test->caps_done, FLAG_TESTED);
  92.             can_test(test->caps_tested, FLAG_TESTED);
  93.             test->test_procedure(test, state, &nch);
  94.         } else
  95.         if (test->sub_menu) {
  96.             /* nested menu's */
  97.             menu_display(test->sub_menu, &nch);
  98.             *state = 0;
  99.             if (nch == 'q' || nch == 's') {
  100.                 /* Quit and skip are killed here */
  101.                 nch = '?';
  102.             }
  103.         } else {
  104.             break;    /* cya */
  105.         }
  106.         if (nch == '\r' || nch == '\n' || nch == 'n') {
  107.             nch = 0;
  108.             break;
  109.         }
  110.     } while (nch == 'r');
  111.     *ch = nch;
  112. }
  113.  
  114. /*
  115. **    menu_display(menu-structure, flags)
  116. **
  117. **    This function implements menu control.
  118. */
  119. void
  120. menu_display(
  121.     struct test_menu *menu,
  122.     int *last_ch)
  123. {
  124.     int test_state = 0, run_standard_tests;
  125.     int hot_topic, ch = 0, nch = 0;
  126.     struct test_list *mt;
  127.     struct test_list *repeat_tests = 0;
  128.     int repeat_state = 0;
  129.     int prompt_length;
  130.  
  131.     prompt_length = strlen(prompt_string);
  132.     if (menu->ident) {
  133.         sprintf(&prompt_string[prompt_length], "/%s", menu->ident);
  134.     }
  135.     hot_topic = menu->default_action;
  136.     run_standard_tests = menu->standard_tests ?
  137.         menu->standard_tests[0] : -1;
  138.     if (!last_ch) {
  139.         last_ch = &ch;
  140.     }
  141.     while (1) {
  142.         if (ch == 0) {
  143.             /* Display the menu */
  144.             put_crlf();
  145.             if (menu->menu_function) {
  146.                 /*
  147.                    this function may be used to restrict menu
  148.                    entries.  If used it must print the title.
  149.                 */
  150.                 menu->menu_function(menu);
  151.             } else
  152.             if (menu->menu_title) {
  153.                 ptextln(menu->menu_title);
  154.             }
  155.             for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
  156.                 if (mt->menu_entry) {
  157.                     ptext(" ");
  158.                     ptextln(mt->menu_entry);
  159.                 }
  160.             }
  161.             if (menu->standard_tests) {
  162.                 ptext(" ");
  163.                 ptextln(menu->standard_tests);
  164.                 ptextln(" r) repeat test");
  165.                 ptextln(" s) skip to next test");
  166.             }
  167.             ptextln(" q) quit");
  168.             ptextln(" ?) help");
  169.         }
  170.         if (ch == 0 || ch == REQUEST_PROMPT) {
  171.             put_crlf();
  172.             ptext(&prompt_string[1]);
  173.             if (hot_topic) {
  174.                 ptext(" [");
  175.                 putchp(hot_topic);
  176.                 ptext("]");
  177.             }
  178.             ptext(" > ");
  179.             /* read a character */
  180.             ch = wait_here();
  181.         }
  182.         if (ch == '\r' || ch == '\n') {
  183.             ch = hot_topic;
  184.         }
  185.         if (ch == 'q') {
  186.             break;
  187.         }
  188.         if (ch == '?') {
  189.             ch = 0;
  190.             continue;
  191.         }
  192.         nch = ch;
  193.         ch = 0;
  194.         /* Run one of the standard tests (by request) */
  195.         for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
  196.             if (mt->menu_entry && (nch == mt->menu_entry[0])) {
  197.                 if (mt->flags & MENU_MENU) {
  198.                     test_byname(menu, &test_state, &nch);
  199.                 } else {
  200.                     menu_test_loop(mt, &test_state, &nch);
  201.                 }
  202.                 ch = nch;
  203.                 if ((mt->flags & MENU_COMPLETE) && ch == 0) {
  204.                     /* top level */
  205.                     hot_topic = 'q';
  206.                     ch = '?';
  207.                 }
  208.             }
  209.         }
  210.         if (menu->standard_tests && nch == 'r') {
  211.             menu->resume_tests = repeat_tests;
  212.             test_state = repeat_state;
  213.             nch = run_standard_tests;
  214.         }
  215.         if (nch == run_standard_tests) {
  216.             if (!(mt = menu->resume_tests)) {
  217.                 mt = menu->tests;
  218.             }
  219.             if (mt->flags & MENU_LAST) {
  220.                 mt = menu->tests;
  221.             }
  222.             /* Run the standard test suite */
  223.             for ( ; (mt->flags & MENU_LAST) == 0; ) {
  224.                 if ((mt->flags & MENU_NEXT) == MENU_NEXT) {
  225.                     repeat_tests = mt;
  226.                     repeat_state = test_state;
  227.                     nch = run_standard_tests;
  228.                     menu_test_loop(mt, &test_state, &nch);
  229.                     if (nch != 0 && nch != 'n') {
  230.                         ch = nch;
  231.                         break;
  232.                     }
  233.                     if (test_state & MENU_STOP) {
  234.                         break;
  235.                     }
  236.                 }
  237.                 mt++;
  238.             }
  239.             if (ch == 0) {
  240.                 ch = hot_topic;
  241.             }
  242.             menu->resume_tests = mt;
  243.             menu->resume_state = test_state;
  244.             menu->resume_char = ch;
  245.  
  246.             if (ch == run_standard_tests) {
  247.                 /* pop up a level */
  248.                 break;
  249.             }
  250.         }
  251.     }
  252.     *last_ch = ch;
  253.     prompt_string[prompt_length] = '\0';
  254. }
  255.  
  256. /*
  257. **    generic_done_message(test_list)
  258. **
  259. **    Print the Done message and request input.
  260. */
  261. void
  262. generic_done_message(
  263.     struct test_list *test,
  264.     int *state,
  265.     int *ch)
  266. {
  267.     char done_message[128];
  268.  
  269.     if (test->caps_done) {
  270.         sprintf(done_message, "(%s) Done ", test->caps_done);
  271.         ptext(done_message);
  272.     } else {
  273.         ptext("Done ");
  274.     }
  275.     *ch = wait_here();
  276.     if (*ch == '\r' || *ch == '\n' || *ch == 'n') {
  277.         *ch = 0;
  278.     }
  279.     if (*ch == 's') {
  280.         *state |= MENU_STOP;
  281.         *ch = 0;
  282.     }
  283. }
  284.  
  285. /*
  286. **    menu_clear_screen(test, state, ch)
  287. **
  288. **    Just clear the screen.
  289. */
  290. void
  291. menu_clear_screen(
  292.     struct test_list *test GCC_UNUSED,
  293.     int *state GCC_UNUSED,
  294.     int *ch GCC_UNUSED)
  295. {
  296.     put_clear();
  297. }
  298.  
  299. /*
  300. **    menu_reset_init(test, state, ch)
  301. **
  302. **    Send the reset and init strings.
  303. */
  304. void
  305. menu_reset_init(
  306.     struct test_list *test GCC_UNUSED,
  307.     int *state GCC_UNUSED,
  308.     int *ch GCC_UNUSED)
  309. {
  310.     reset_init();
  311.     put_crlf();
  312. }
  313.  
  314. /*
  315. **    subtest_menu(test, state, ch)
  316. **
  317. **    Scan the menu looking for something to execute
  318. **    Return TRUE if we found anything.
  319. */
  320. int
  321. subtest_menu(
  322.     struct test_list *test,
  323.     int *state,
  324.     int *ch)
  325. {
  326.     struct test_list *mt;
  327.  
  328.     if (*ch) {
  329.         for (mt = test; (mt->flags & MENU_LAST) == 0; mt++) {
  330.             if (mt->menu_entry && (*ch == mt->menu_entry[0])) {
  331.                 *ch = 0;
  332.                 menu_test_loop(mt, state, ch);
  333.                 return TRUE;
  334.             }
  335.         }
  336.     }
  337.     return FALSE;
  338. }
  339.  
  340. /*
  341. **    menu_can_scan(menu-structure)
  342. **
  343. **    Recursively scan the menu tree and find which cap names can be tested.
  344. */
  345. void
  346. menu_can_scan(
  347.     const struct test_menu *menu)
  348. {
  349.     struct test_list *mt;
  350.  
  351.     for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
  352.         can_test(mt->caps_done, FLAG_CAN_TEST);
  353.         can_test(mt->caps_tested, FLAG_CAN_TEST);
  354.         if (!(mt->test_procedure)) {
  355.             if (mt->sub_menu) {
  356.                 menu_can_scan(mt->sub_menu);
  357.             }
  358.         }
  359.     }
  360. }
  361.  
  362. /*
  363. **    menu_search(menu-structure, cap)
  364. **
  365. **    Recursively search the menu tree and execute any tests that use cap.
  366. */
  367. static void
  368. menu_search(
  369.     struct test_menu *menu,
  370.     int *state,
  371.     int *ch,
  372.     char *cap)
  373. {
  374.     struct test_list *mt;
  375.     int nch;
  376.  
  377.     for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
  378.         nch = 0;
  379.         if (cap_match(mt->caps_done, cap)
  380.             || cap_match(mt->caps_tested, cap)) {
  381.             menu_test_loop(mt, state, &nch);
  382.         }
  383.         if (!(mt->test_procedure)) {
  384.             if (mt->sub_menu) {
  385.                 menu_search(mt->sub_menu, state, &nch, cap);
  386.             }
  387.         }
  388.         if (*state & MENU_STOP) {
  389.             break;
  390.         }
  391.         if (nch != 0 && nch != 'n') {
  392.             *ch = nch;
  393.             break;
  394.         }
  395.     }
  396. }
  397.  
  398. /*
  399. **    test_byname(menu, state, ch)
  400. **
  401. **    Get a cap name then run all tests that use that cap.
  402. */
  403. static void
  404. test_byname(
  405.     struct test_menu *menu,
  406.     int *state GCC_UNUSED,
  407.     int *ch)
  408. {
  409.     int test_state = 0;
  410.     char cap[32];
  411.  
  412.     if (tty_can_sync == SYNC_NOT_TESTED) {
  413.         verify_time();
  414.     }
  415.     ptext("enter name: ");
  416.     read_string(cap, sizeof(cap));
  417.     if (cap[0]) {
  418.         menu_search(menu, &test_state, ch, cap);
  419.     }
  420.     *ch = '?';
  421. }
  422.